package processes;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * The process ADT, used to create processes of various types.
 * 
 * @author kyle
 * @version 3.8.13
 * 
 */
public abstract class Process {

	/**
	 * Length of instruction set.
	 */
	public static final int INST_SIZE = 100;

	/**
	 * The list of commands.
	 */
	protected List<String> my_inst;
	
	/**
	 * The name of the process.
	 */
	protected String my_name;

	/**
	 * Is this process runnable?
	 */
	protected boolean my_isRunnable;

	/**
	 * The current instruction when the process is blocked.
	 */
	protected int my_inst_index;

	/**
	 * The priority of the process.
	 */
	public int my_priority;

	/**
	 * An instruction that is useful.
	 */
	protected String my_imp_inst;

	/**
	 * The indexed priority.
	 */
	public int my_conc_priority;

	/**
	 * List of possible instructions.
	 */
	protected List<String> my_possible_inst;

	public Process() {
		my_isRunnable = true;
		addPossibleInst();
		generateInst();
	}

	/**
	 * Overloaded constructor for priority.
	 */
	public Process(int the_priority) {
		this();
		my_priority = the_priority;
		my_conc_priority = the_priority;
	}
	
	/**
	 * Sets the priority to param.
	 */
	public void setPriority(int the_p)
	{
		my_priority = the_p;
	}

	/**
	 * Adds the possible instructions.
	 * 
	 * @return
	 */
	protected abstract void addPossibleInst();

	/**
	 * Generates random list of instructions.
	 */
	protected void generateInst() {
		my_inst = new ArrayList<>();
		Random rand = new Random();
		for (int i = 0; i < Process.INST_SIZE; i++) {
			if (Math.abs(rand.nextInt() % 1000) == 0) {
				my_inst.add(my_imp_inst);
			} else {
				int index = Math.abs(rand.nextInt()) % my_possible_inst.size();
				my_inst.add(my_possible_inst.get(index));
			}
		}
	}

	/**
	 * What are my instructions?
	 * 
	 * @return What are my instructions?
	 */
	public List<String> getInst() {
		return new ArrayList<String>(my_inst);
	}

	/**
	 * Am I runnable?
	 */
	public boolean canRun() {
		return my_isRunnable;
	}
	

	/**
	 * Makes the process not runnable.
	 */
	public void block() {
		my_isRunnable = false;
	}

	/**
	 * Makes the process runnable.
	 */
	public void unblock() {
		my_isRunnable = true;
	}
	
	/**
	 * Returns the name of the process.
	 */
	public String getName()
	{
		return my_name;
	}

	/**
	 * Gets the last index of instruction.
	 */
	public int getIndex() {
		return my_inst_index;
	}

	/**
	 * Stores the current index in the instructions.
	 */
	public void storeIndex(int the_index) {
		my_inst_index = the_index;
	}

}
